home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / twave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  19.5 KB  |  806 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <GL/glu.h>
  18. #include <GL/glx.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <X11/keysym.h>
  22. #include <string.h>
  23. #include <math.h>
  24.  
  25. static int RGBA_SB_attributes[] = {
  26.     GLX_RGBA,
  27.     GLX_RED_SIZE, 1,
  28.     GLX_GREEN_SIZE, 1,
  29.     GLX_BLUE_SIZE, 1,
  30.     GLX_DEPTH_SIZE, 1,
  31.     GLX_STENCIL_SIZE, 1,
  32.     None,
  33. };
  34.  
  35. static int RGBA_DB_attributes[] = {
  36.     GLX_RGBA,
  37.     GLX_RED_SIZE, 1,
  38.     GLX_GREEN_SIZE, 1,
  39.     GLX_BLUE_SIZE, 1,
  40.     GLX_DOUBLEBUFFER,
  41.     GLX_DEPTH_SIZE, 1,
  42.     GLX_STENCIL_SIZE, 1,
  43.     None,
  44. };
  45.  
  46. static int CI_SB_attributes[] = {
  47.     GLX_DEPTH_SIZE, 1,
  48.     GLX_STENCIL_SIZE, 1,
  49.     None,
  50. };
  51.  
  52. static int CI_DB_attributes[] = {
  53.     GLX_DOUBLEBUFFER,
  54.     GLX_DEPTH_SIZE, 1,
  55.     GLX_STENCIL_SIZE, 1,
  56.     None,
  57. };
  58.  
  59. #define PI        3.14159265358979323846
  60.  
  61. static int W = 300;
  62. static int H = 300;
  63.  
  64. static int rgb;
  65. static int doubleBuffer;
  66. static int indexBits;
  67.  
  68. static long clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
  69. static int overStrike = 0;
  70. static int smooth=0;
  71. static int lighting=1;
  72. static int depth=1;
  73. static int fog=0;
  74. static int stepmode=0;
  75. static int checkersize = 2;
  76. static int spinmode = 0;
  77. static int curframe;
  78. static int nextframe = 0;
  79. static float height = 0.2;
  80. static int contouring;
  81.  
  82. static int colorIndexes1[3];
  83. static int colorIndexes2[3];
  84.  
  85. Display *dpy;
  86. Window window;
  87. Colormap cmap;
  88.  
  89. #define YWIDTH    10
  90. #define XWIDTH    10
  91. #define FRAMES  10
  92.  
  93. struct facet {
  94.     float color[3];
  95.     float normal[3];
  96. };
  97.  
  98. struct coord {
  99.     float vertex[3];
  100.     float normal[3];
  101. };
  102.  
  103. struct mesh {
  104.     int xwidth, ywidth;
  105.     int nfacets;
  106.     int ncoords;
  107.     int frames;
  108.     struct coord *coords;
  109.     struct facet *facets;
  110. } theMesh;
  111.  
  112. #define GETCOORD(frame, x, y) (&(theMesh.coords[frame * theMesh.ncoords + (x) + (y) * (theMesh.xwidth+1)]))
  113.  
  114. #define GETFACET(frame, x, y) (&(theMesh.facets[frame * theMesh.nfacets + (x) + (y) * theMesh.xwidth]))
  115.  
  116. unsigned char contourTexture[] = {
  117.     255, 255, 255, 255,
  118.     255, 255, 255, 255,
  119.     255, 255, 255, 255,
  120.     127, 127, 127, 127,
  121. };
  122.  
  123. unsigned char contourTexture2[] = {
  124.     255, 255, 255, 255,
  125.     255, 127, 127, 127,
  126.     255, 127, 127, 127,
  127.     255, 127, 127, 127,
  128. };
  129.  
  130. static void setColorMap(void) 
  131. {
  132.     int i;
  133.     int j;
  134.     int *indexes;
  135.     float *color;
  136.     static float green[3] = { 0.2, 1.0, 0.2 };
  137.     static float red[3] = { 1.0, 0.2, 0.2 };
  138.     float r,g,b;
  139.     float percent;
  140.     long buf[4];
  141.     int entries;
  142.     XColor *colors;
  143.  
  144.     entries = (1 << indexBits) - 1;
  145.     colorIndexes1[0] = 1;
  146.     colorIndexes1[1] = 1 + (entries * 0.3);
  147.     colorIndexes1[2] = (entries * 0.5);
  148.     colorIndexes2[0] = 1 + (entries * 0.5);
  149.     colorIndexes2[1] = 1 + (entries * 0.8);
  150.     colorIndexes2[2] = entries;
  151.  
  152.     colors = (XColor*) calloc(entries+1, sizeof(XColor));
  153.  
  154.     for (i=0; i<2; i++) {
  155.     switch (i) {
  156.     case 0:
  157.         color=green;
  158.         indexes=colorIndexes1;
  159.         break;
  160.     case 1:
  161.         color=red;
  162.         indexes=colorIndexes2;
  163.         break;
  164.     }
  165.     for (j=indexes[0]; j<indexes[1]; j++) {
  166.         /* 20% ambient, 80% diffuse */
  167.         percent=0.2 + 0.8*(j-indexes[0]) / (float) (indexes[1]-indexes[0]);
  168.         colors[j].pixel = j;
  169.         colors[j].red = 65535 * (percent*color[0]) + 0.5;
  170.         colors[j].green = 65535 * (percent*color[1]) + 0.5;
  171.         colors[j].blue = 65535 * (percent*color[2]) + 0.5;
  172.         colors[j].flags = DoRed|DoGreen|DoBlue;
  173.     }
  174.     for (j=indexes[1]; j<=indexes[2]; j++) {
  175.         /* Specular goes to white */
  176.         percent=(j-indexes[1]) / (float) (indexes[2]-indexes[1]);
  177.         colors[j].pixel = j;
  178.         colors[j].red = 65535 * (percent*(1-color[0]) + color[0]) + 0.5;
  179.         colors[j].green = 65535 * (percent*(1-color[1]) + color[1]) + 0.5;
  180.         colors[j].blue = 65535 * (percent*(1-color[2]) + color[2]) + 0.5;
  181.         colors[j].flags = DoRed|DoGreen|DoBlue;
  182.     }
  183.     }
  184.     XStoreColors(dpy, cmap, colors, entries+1);
  185. }
  186.  
  187. static void initialize(int xwidth, int ywidth, int frames)
  188. {
  189.     int nfacets;
  190.     int ncoords;
  191.     int i,j;
  192.     int frameno;
  193.     float x, y;
  194.     float angle;
  195.     float d;
  196.     struct coord *coord;
  197.     struct facet *facet;
  198.     float *pt1, *pt2, *pt3;
  199.     float dp1[3], dp2[3];
  200.  
  201.     theMesh.xwidth=xwidth;
  202.     theMesh.ywidth=ywidth;
  203.     theMesh.frames=frames;
  204.  
  205.     nfacets=xwidth*ywidth;
  206.     ncoords=(xwidth+1)*(ywidth+1);
  207.  
  208.     theMesh.ncoords=ncoords;
  209.     theMesh.nfacets=nfacets;
  210.  
  211.     theMesh.coords=
  212.     (struct coord *) malloc(frames * ncoords * sizeof(struct coord));
  213.     theMesh.facets=
  214.     (struct facet *) malloc(frames * nfacets * sizeof(struct facet));
  215.     if (theMesh.coords == NULL || theMesh.facets == NULL) {
  216.     printf("Out of memory.\n");
  217.     exit(-1);
  218.     }
  219.  
  220.     for (frameno = 0; frameno < frames; frameno++) {
  221.     for (i = 0; i <= xwidth; i++) {
  222.         x = i / (float) xwidth;
  223.         for (j = 0; j <= ywidth; j++) {
  224.         y = j / (float) ywidth;
  225.  
  226.         d=sqrt(x*x + y*y);
  227.         if (d == 0.0) d=0.0001;
  228.         angle=2*PI*d + (2*PI/frames * frameno);
  229.  
  230.         coord = GETCOORD(frameno, i, j);
  231.  
  232.         coord->vertex[0] = x - 0.5;
  233.         coord->vertex[1] = y - 0.5;
  234.         coord->vertex[2] = (height - height*d) * cos(angle);
  235.         coord->normal[0] = 
  236.             -(height/d) * x * ((1-d) * 2*PI*sin(angle) + cos(angle));
  237.         coord->normal[1] = 
  238.             -(height/d) * y * ((1-d) * 2*PI*sin(angle) + cos(angle));
  239.         coord->normal[2] = -1;
  240.  
  241.         d = 1.0 / sqrt(coord->normal[0] * coord->normal[0] +
  242.                    coord->normal[1] * coord->normal[1] + 1);
  243.         coord->normal[0] *= d;
  244.         coord->normal[1] *= d;
  245.         coord->normal[2] *= d;
  246.         }
  247.     }
  248.     for (i = 0; i < xwidth; i++) {
  249.         for (j = 0; j < ywidth; j++) {
  250.         facet = GETFACET(frameno, i, j);
  251.         if (((i / checkersize) % 2) ^ (j / checkersize) % 2) {
  252.             if (rgb) {
  253.             facet->color[0] = 1.0;
  254.             facet->color[1] = 0.2;
  255.             facet->color[2] = 0.2;
  256.             } else {
  257.             facet->color[0] = colorIndexes1[0];
  258.             facet->color[1] = colorIndexes1[1];
  259.             facet->color[2] = colorIndexes1[2];
  260.             }
  261.         } else {
  262.             if (rgb) {
  263.             facet->color[0] = 0.2;
  264.             facet->color[1] = 1.0;
  265.             facet->color[2] = 0.2;
  266.             } else {
  267.             facet->color[0] = colorIndexes2[0];
  268.             facet->color[1] = colorIndexes2[1];
  269.             facet->color[2] = colorIndexes2[2];
  270.             }
  271.         }
  272.         pt1 = GETCOORD(frameno, i, j)->vertex;
  273.         pt2 = GETCOORD(frameno, i, j+1)->vertex;
  274.         pt3 = GETCOORD(frameno, i+1, j+1)->vertex;
  275.  
  276.         dp1[0] = pt2[0]-pt1[0];
  277.         dp1[1] = pt2[1]-pt1[1];
  278.         dp1[2] = pt2[2]-pt1[2];
  279.  
  280.         dp2[0] = pt3[0]-pt2[0];
  281.         dp2[1] = pt3[1]-pt2[1];
  282.         dp2[2] = pt3[2]-pt2[2];
  283.  
  284.         facet->normal[0] = dp1[1] * dp2[2] - dp1[2] * dp2[1];
  285.         facet->normal[1] = dp1[2] * dp2[0] - dp1[0] * dp2[2];
  286.         facet->normal[2] = dp1[0] * dp2[1] - dp1[1] * dp2[0];
  287.  
  288.         d = 1.0 / sqrt(facet->normal[0] * facet->normal[0] +
  289.             facet->normal[1] * facet->normal[1] +
  290.             facet->normal[2] * facet->normal[2]);
  291.  
  292.         facet->normal[0] *= d;
  293.         facet->normal[1] *= d;
  294.         facet->normal[2] *= d;
  295.         }
  296.     }
  297.     }
  298. }
  299.  
  300. static void initMaterials(void)
  301. {
  302.     static float ambient[] = { 0.1, 0.1, 0.1, 1.0 };
  303.     static float diffuse[] = { 0.5, 1.0, 1.0, 1.0 };
  304.     static float position[] = { 90.0, 90.0, 150.0, 0.0 };
  305.     static float front_mat_shininess[] = { 60.0 };
  306.     static float front_mat_specular[] = { 0.2, 0.2, 0.2, 1.0 };
  307.     static float front_mat_diffuse[] = { 0.5, 0.28, 0.38, 1.0 };
  308.     static float back_mat_shininess[] = { 60.0 };
  309.     static float back_mat_specular[] = { 0.5, 0.5, 0.2, 1.0 };
  310.     static float back_mat_diffuse[] = { 1.0, 1.0, 0.2, 1.0 };
  311.     static float lmodel_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
  312.     static float lmodel_twoside[] = { GL_TRUE };
  313.     static float fog_color[] = {0.0, 0.0, 0.0, 1.0};
  314.     
  315.     glFrontFace(GL_CW);
  316.     glEnable(GL_DEPTH_TEST);
  317.     glDepthFunc(GL_LEQUAL);
  318.  
  319.     glMatrixMode(GL_PROJECTION);
  320.     gluPerspective(450, 1.0, 0.5, 10.0);
  321.     glClearColor(0.0, 0.0, 0.0, 0.0);
  322.  
  323.     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  324.     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  325.     glLightfv(GL_LIGHT0, GL_POSITION, position);
  326.     
  327.     glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
  328.     glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
  329.     glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
  330.     glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
  331.     glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
  332.     glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
  333.  
  334.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  335.     glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
  336.  
  337.     glEnable(GL_LIGHTING);
  338.     glEnable(GL_LIGHT0);
  339.     glShadeModel(GL_FLAT);
  340.  
  341.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  342.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  343.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  344.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  345.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  346.  
  347.     if (rgb) {
  348.     glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  349.     glEnable(GL_COLOR_MATERIAL);
  350.     glFogf(GL_FOG_END, 5.0);
  351.     glFogf(GL_FOG_START, 0.25);
  352.     glFogi(GL_FOG_MODE, GL_LINEAR);
  353.     glFogfv(GL_FOG_COLOR, fog_color);
  354.     } else {
  355.     setColorMap();
  356.     }
  357. }
  358.  
  359. static void redraw(void)
  360. {
  361.     struct coord *coord;
  362.     struct facet *facet;
  363.     float *lastcolor;
  364.     float *thiscolor;
  365.     int i,j;
  366.  
  367.     glClearColor(0.0, 0.0, 0.0, 0.0);
  368.     glClear(clearMask);
  369.  
  370.     if (!stepmode) curframe++;
  371.  
  372.     if (!stepmode && spinmode) {
  373.     glRotatef(5.0, 0.0, 0.0, 1.0);
  374.     }
  375.  
  376.     while (nextframe) {
  377.     curframe++;
  378.     if (spinmode) {
  379.         glRotatef(5.0, 0.0, 0.0, 1.0);
  380.     }
  381.     nextframe--;
  382.     }
  383.     nextframe = 0;
  384.     while (curframe >= theMesh.frames) curframe -= theMesh.frames;
  385.  
  386.     for (i = 0; i < theMesh.xwidth; i++) {
  387.     glBegin(GL_QUAD_STRIP);
  388.     lastcolor = NULL;
  389.     for (j = 0; j < theMesh.ywidth; j++) {
  390.         facet=GETFACET(curframe, i, j);
  391.         if (!smooth && lighting) {
  392.         glNormal3fv(facet->normal);
  393.         }
  394.         if (lighting) {
  395.         if (rgb) {
  396.             thiscolor = facet->color;
  397.             glColor3fv(facet->color);
  398.         } else {
  399.             thiscolor = facet->color;
  400.             glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, 
  401.                  facet->color);
  402.         }
  403.         } else {
  404.         if (rgb) {
  405.             thiscolor = facet->color;
  406.             glColor3fv(facet->color);
  407.         } else {
  408.             thiscolor = facet->color;
  409.             glIndexf(facet->color[1]);
  410.         }
  411.         }
  412.  
  413.         /* Need to draw first two verts? */
  414.         if (!lastcolor || 
  415.         (thiscolor[0] != lastcolor[0] && smooth)) {
  416.         if (lastcolor) {
  417.             glEnd();
  418.             glBegin(GL_QUAD_STRIP);
  419.         }
  420.         coord=GETCOORD(curframe, i, j);
  421.         if (smooth && lighting) {
  422.             glNormal3fv(coord->normal);
  423.         }
  424.         glVertex3fv(coord->vertex);
  425.  
  426.         coord=GETCOORD(curframe, i+1, j);
  427.         if (smooth && lighting) {
  428.             glNormal3fv(coord->normal);
  429.         }
  430.         glVertex3fv(coord->vertex);
  431.         }
  432.  
  433.         coord=GETCOORD(curframe, i, j+1);
  434.         if (smooth && lighting) {
  435.         glNormal3fv(coord->normal);
  436.         }
  437.         glVertex3fv(coord->vertex);
  438.  
  439.         coord=GETCOORD(curframe, i+1, j+1);
  440.         if (smooth && lighting) {
  441.         glNormal3fv(coord->normal);
  442.         }
  443.         glVertex3fv(coord->vertex);
  444.  
  445.         lastcolor = thiscolor;
  446.     }
  447.     glEnd();
  448.     }
  449.     glFlush();
  450.     if (doubleBuffer) {
  451.     glXSwapBuffers(dpy, window);
  452.     }
  453. }
  454.  
  455. static void animate(void)
  456. {
  457.     int rv, needRedraw;
  458.     KeySym ks;
  459.     char buf[10];
  460.     XEvent ev;
  461.  
  462.     needRedraw = 1;
  463.     for (;;) {
  464.     while (XPending(dpy)) {
  465.         XNextEvent(dpy, &ev);
  466.  
  467.         switch (ev.type) {
  468.           case Expose:
  469.         needRedraw = 1;
  470.         break;
  471.           case ConfigureNotify:
  472.         W = ev.xconfigure.width;
  473.         H = ev.xconfigure.height;
  474.         glViewport(0, 0, W, H);
  475.         needRedraw = 1;
  476.         break;
  477.           case KeyPress:
  478.         rv = XLookupString(&ev.xkey, buf, sizeof(buf), &ks, 0);
  479.         needRedraw = 1;
  480.         switch (ks) {
  481.           case XK_Escape:
  482.             return;
  483.           case XK_C:
  484.           case XK_c:
  485.             contouring++;
  486.             if (contouring == 1) {
  487.             static GLfloat map[4] = { 0, 0, 20, 0 };
  488.  
  489.             glTexImage2D(GL_TEXTURE_2D, 0, 3, 4, 4, 0,
  490.                      GL_LUMINANCE, GL_UNSIGNED_BYTE, 
  491.                      (const unsigned char *) contourTexture);
  492.             glEnable(GL_TEXTURE_2D);
  493.             glEnable(GL_TEXTURE_GEN_S);
  494.             glEnable(GL_TEXTURE_GEN_T);
  495.             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  496.             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  497.             glTexGenfv(GL_S, GL_OBJECT_PLANE, map);
  498.             glTexGenfv(GL_T, GL_OBJECT_PLANE, map);
  499.             } else if (contouring == 2) {
  500.             static GLfloat map[4] = { 0, 0, 20, 0 };
  501.  
  502.             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  503.             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  504.             glPushMatrix();
  505.             glLoadIdentity();
  506.             glTexGenfv(GL_S, GL_EYE_PLANE, map);
  507.             glTexGenfv(GL_T, GL_EYE_PLANE, map);
  508.             glPopMatrix();
  509.             } else {
  510.             contouring = 0;
  511.             glDisable(GL_TEXTURE_2D);
  512.             glDisable(GL_TEXTURE_GEN_S);
  513.             glDisable(GL_TEXTURE_GEN_T);
  514.             }
  515.             break;
  516.           case XK_S: case XK_s:
  517.             smooth=1-smooth;
  518.             if (smooth) {
  519.             glShadeModel(GL_SMOOTH);
  520.             } else {
  521.             glShadeModel(GL_FLAT);
  522.             }
  523.             break;
  524.           case XK_L: case XK_l:
  525.             lighting=1-lighting;
  526.             if (lighting) {
  527.             glEnable(GL_LIGHTING);
  528.             glEnable(GL_LIGHT0);
  529.             if (rgb) {
  530.                 glEnable(GL_COLOR_MATERIAL);
  531.             }
  532.             } else {
  533.             glDisable(GL_LIGHTING);
  534.             glDisable(GL_LIGHT0);
  535.             if (rgb) {
  536.                 glDisable(GL_COLOR_MATERIAL);
  537.             }
  538.             }
  539.             break;
  540.           case XK_D: case XK_d:
  541.             depth=1-depth;
  542.             if (depth) {
  543.             glEnable(GL_DEPTH_TEST);
  544.             clearMask |= GL_DEPTH_BUFFER_BIT;
  545.             printf("Depth on\n");
  546.             } else {
  547.             glDisable(GL_DEPTH_TEST);
  548.             clearMask &= ~GL_DEPTH_BUFFER_BIT;
  549.             printf("Depth off\n");
  550.             }
  551.             break;
  552.           case XK_O: case XK_o:
  553.             overStrike = 1 - overStrike;
  554.             if (overStrike) {
  555.             glEnable(GL_STENCIL_TEST);
  556.             glStencilFunc(GL_EQUAL, 0, ~0);
  557.             glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  558.             clearMask |= GL_STENCIL_BUFFER_BIT;
  559.             printf("Overstrike on\n");
  560.             } else {
  561.             glDisable(GL_STENCIL_TEST);
  562.             printf("Overstrike off\n");
  563.             }
  564.             break;
  565.           case XK_F: case XK_f:
  566.             if (rgb) {
  567.             fog = !fog;
  568.             fog ? glEnable(GL_FOG) : glDisable(GL_FOG);
  569.             }
  570.             break;
  571.           case XK_space:
  572.             stepmode=1-stepmode;
  573.             break;
  574.           case XK_N:
  575.           case XK_n:
  576.             if (stepmode) {
  577.             nextframe++;
  578.             }
  579.             break;
  580.           case XK_A:
  581.           case XK_a:
  582.             spinmode = 1-spinmode;
  583.             break;
  584.           default:
  585.             break;
  586.         }
  587.         break;
  588.         }
  589.     }
  590.     if (!stepmode || needRedraw) {
  591.         redraw();
  592.         needRedraw = 0;
  593.     }
  594.     if (stepmode) {
  595.         XPeekEvent(dpy, &ev);
  596.     }
  597.     }
  598. }
  599.  
  600. static void usage(void)
  601. {
  602.     printf("\
  603. Usage: twave [-g width height] [-f frames] [-c] [-s] [-b checker size]\n\
  604.          [-h height] [-geometry WxH+X+Y] [-a]\n\
  605.    -g:  Specify grid size  (default is 10 by 10)\n\
  606.    -f:  Specify number of frames in a full cycle  (default is 10)\n\
  607.    -c:    Run in color index mode\n\
  608.    -s:  Run in single buffered mode\n\
  609.    -b:  Specify size of checker on checker board  (default is 2)\n\
  610.    -h:  Specify the height of the wave  (default is 0.2)\n\
  611.    -a:  Don't start off animating.\n\
  612.    -geometry:  Specify window size and location\n\
  613. ");
  614.     exit(-1);
  615. }
  616.  
  617. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  618. {
  619.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  620.     return GL_TRUE;
  621.     }
  622.     return GL_FALSE;
  623. }
  624.  
  625. int main(int argc, char **argv)
  626. {
  627.     int xwidth, ywidth;
  628.     int frames;
  629.     int i;
  630.     int *attrs;
  631.     XVisualInfo *vi;
  632.     XSetWindowAttributes swa;
  633.     XEvent event;
  634.     GLXContext cx;
  635.     char window_title[100];
  636.     XSizeHints sizehints;
  637.     char *geometry = NULL;
  638.  
  639.     rgb=1;
  640.     doubleBuffer = 1;
  641.  
  642.     xwidth=XWIDTH;
  643.     ywidth=YWIDTH;
  644.     frames=FRAMES;
  645.     for (i=1; i<argc; i++) {
  646.     if (!strcmp(argv[i], "-geometry")) {
  647.         i++;
  648.         geometry = argv[i];
  649.     } else if (argv[i][0] == '-') {
  650.         switch(argv[i][1]) {
  651.           case 'g':
  652.         i++;
  653.         if (argv[i] == NULL) usage();
  654.         xwidth=atoi(argv[i]);
  655.         i++;
  656.         if (argv[i] == NULL) usage();
  657.         ywidth=atoi(argv[i]);
  658.         if (xwidth <= 0 || ywidth <= 0) {
  659.             printf("Non-positive widths not allowed.\n");
  660.             return -1;
  661.         }
  662.         break;
  663.           case 'f':
  664.         i++;
  665.         if (argv[i] == NULL) usage();
  666.         frames=atoi(argv[i]);
  667.         if (frames < 1) {
  668.             printf("Must have at least 1 frame\n");
  669.             return -1;
  670.         }
  671.         break;
  672.           case 'h':
  673.         i++;
  674.         if (argv[i] == NULL) usage();
  675.         height=atof(argv[i]);
  676.         break;
  677.           case 'c':
  678.         rgb=0;
  679.         break;
  680.           case 's':
  681.         doubleBuffer = 0;
  682.         break;
  683.           case 'a':    /* animation off mode */
  684.         stepmode = 1;
  685.         break;
  686.           case 'b':
  687.         i++;
  688.         if (argv[i] == NULL) usage();
  689.         checkersize=atoi(argv[i]);
  690.         if (checkersize < 1) {
  691.             printf("Checker Size must be at least 1\n");
  692.             return -1;
  693.         }
  694.         break;
  695.           default:
  696.         usage();
  697.         }
  698.     } else usage();
  699.     }
  700.  
  701.     if (doubleBuffer) {
  702.     if (rgb) {
  703.         attrs = RGBA_DB_attributes;
  704.     } else {
  705.         attrs = CI_DB_attributes;
  706.     }
  707.     } else {
  708.     if (rgb) {
  709.         attrs = RGBA_SB_attributes;
  710.     } else {
  711.         attrs = CI_SB_attributes;
  712.     }
  713.     }
  714.  
  715.     dpy = XOpenDisplay(0);
  716.     if (!dpy) {
  717.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  718.     return -1;
  719.     }
  720.  
  721.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attrs);
  722.     if (!vi) {
  723.     fprintf(stderr, "No matching visual on \"%s\"\n",
  724.         getenv("DISPLAY"));
  725.     return -1;
  726.     }
  727.  
  728.     sizehints.flags = PPosition | PSize;
  729.     sizehints.width = W;
  730.     sizehints.height = H;
  731.     sizehints.x = 10;
  732.     sizehints.y = 10;
  733.     if(geometry) {
  734.     int flags, x, y, width, height;
  735.  
  736.     flags = XParseGeometry(geometry, &x, &y,
  737.                    (unsigned int *)&width,
  738.                    (unsigned int *)&height);
  739.         if(WidthValue & flags) {
  740.         sizehints.flags |= USSize;
  741.         sizehints.width = width;
  742.         W = width;
  743.     }
  744.     if(HeightValue & flags) {
  745.         sizehints.flags |= USSize;
  746.         sizehints.height = height;
  747.         H = height;
  748.     }
  749.     if(XValue & flags) {
  750.         if(XNegative & flags)
  751.         x = DisplayWidth(dpy, DefaultScreen(dpy)) + x 
  752.             - sizehints.width;
  753.                 sizehints.flags |= USPosition;
  754.         sizehints.x = x;
  755.     }
  756.     if(YValue & flags) {
  757.         if(YNegative & flags)
  758.         y = DisplayHeight(dpy, DefaultScreen(dpy)) + y 
  759.             - sizehints.height;
  760.                 sizehints.flags |= USPosition;
  761.         sizehints.y = y;
  762.     }
  763.     }
  764.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  765.                rgb ? AllocNone : AllocAll);
  766.     swa.border_pixel = 0;
  767.     swa.colormap = cmap;
  768.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask;
  769.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  770.                            sizehints.x, sizehints.y,
  771.                sizehints.width, sizehints.height,
  772.                0, vi->depth, InputOutput, vi->visual,
  773.                CWBorderPixel|CWColormap|CWEventMask, &swa);
  774.     sprintf(window_title, "twave (%s %s)",
  775.             rgb ? "RGB" : "CI",
  776.             doubleBuffer ? "double buffered" : "single buffered");
  777.     XSetStandardProperties(dpy, window, window_title, "twave", None,
  778.                            argv, argc, &sizehints);
  779.     XSetWMColormapWindows(dpy, window, &window, 1);
  780.     XMapWindow(dpy, window);
  781.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  782.  
  783.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  784.     if (!glXMakeCurrent(dpy, window, cx)) {
  785.     fprintf(stderr, "Can't make window current to context\n");
  786.     return -1;
  787.     }
  788.     indexBits = vi->depth;
  789.  
  790.     glViewport(0, 0, W, H);
  791.  
  792.     initMaterials();
  793.     initialize(xwidth, ywidth, frames);
  794.  
  795.     glEnable(GL_NORMALIZE);
  796.     glMatrixMode(GL_MODELVIEW);
  797.     glTranslatef(0.0, 0.4, -1.8);
  798.     glScalef(2.0, 2.0, 2.0);
  799.     glRotatef(-35.0, 1.0, 0.0, 0.0);
  800.     glRotatef(35.0, 0.0, 0.0, 1.0);
  801.  
  802.     animate();
  803.  
  804.     return 0;
  805. }
  806.